/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 苏李涛
 * Date: 2024-10-09
 * Time: 20:28
 */

/**
 * 解码方法：
 *
 * 一条包含字母 A-Z 的消息通过以下映射进行了 编码 ：
 *
 * "1" -> 'A'
 *
 * "2" -> 'B'
 *
 * ...
 *
 * "25" -> 'Y'
 *
 * "26" -> 'Z'
 *
 * 然而，在 解码 已编码的消息时，你意识到有许多不同的方式来解码，因为有些编码被包含在其它编码当中（"2" 和 "5" 与 "25"）。
 *
 * 例如，"11106" 可以映射为：
 *
 * "AAJF" ，将消息分组为 (1, 1, 10, 6)
 * "KJF" ，将消息分组为 (11, 10, 6)
 * 消息不能分组为  (1, 11, 06) ，因为 "06" 不是一个合法编码（只有 "6" 是合法的）。
 * 注意，可能存在无法解码的字符串。
 *
 * 给你一个只含数字的 非空 字符串 s ，请计算并返回 解码 方法的 总数 。如果没有合法的方式解码整个字符串，返回 0。
 *
 * 题目数据保证答案肯定是一个 32 位 的整数。
 *
 *
 *
 * 示例 1：
 *
 * 输入：s = "12"
 * 输出：2
 * 解释：它可以解码为 "AB"（1 2）或者 "L"（12）。
 * 示例 2：
 *
 * 输入：s = "226"
 * 输出：3
 * 解释：它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
 * 示例 3：
 *
 * 输入：s = "06"
 * 输出：0
 * 解释："06" 无法映射到 "F" ，因为存在前导零（"6" 和 "06" 并不等价）。
 */
public class DecodingMethod {
    // /**
    // 1.创建dp表
    // 2.初始化
    // 3.填表
    // 4.返回
    //  */
    // public int numDecodings(String ss) {
    //    int n = ss.length();
    //    int[] dp = new int[n];
    //    char[] s = ss.toCharArray();

    //    //初始化第一个位置
    //    if(s[0] != '0') dp[0] = 1;
    //    if(n == 1) return dp[0];//边界情况,只有一位字符时,放置后续越界


    //    /**
    //    初始化第二个位置：
    //    情况一：dp[0],和dp[1]任意一个都可以解码

    //    情况二：dp[0] 和 dp[1]两个可以一起解码
    //     */
    //    if(s[0] != '0' && s[1] != '0') dp[1] += 1;

    //    int t = (s[0] - '0')*10 + (s[1] - '0');
    //    if(t >= 10 && t <= 26) dp[1] += 1;

    //    //3.填表
    //    for(int i = 2; i < n; i++){

    //     //第一种情况：
    //     if(s[i] != '0') dp[i] += dp[i-1];

    //     //情况二：i前面的以及i搜可以编码：
    //     int tt = (s[i-1] - '0')*10 + (s[i] - '0');
    //     if(tt >= 10 && tt <= 26)  dp[i] += dp[i-2];
    //    }

    //    return dp[n-1];
    // }

    //优化版本：
    public int numDecodings(String ss) {
        int n = ss.length();
        int[] dp = new int[n+1];
        char[] s = ss.toCharArray();

        dp[0] = 1;//保证后续填表是正确的

        //初始化第一个位置
        if(s[1-1] != '0') dp[1] = 1;

        //3.填表
        for(int i = 2; i <= n; i++){

            //第一种情况：
            if(s[i-1] != '0') dp[i] += dp[i-1];

            //情况二：i前面的以及i位置都可以编码：
            int tt = (s[i-2] - '0')*10 + (s[i-1] - '0');
            if(tt >= 10 && tt <= 26)  dp[i] += dp[i-2];
        }

        return dp[n];
    }
}
